using System;
using System.Net;
using Moq;
using NUnit.Framework;
using OpenWaves.ActivityFeed.Web;
using OpenWaves.ActivityFeed.Web.Handler;
using OpenWaves.ActivityFeed.Web.Modules;
using System.Linq;

namespace OpenWaves.ActivityFeed.UnitTests.Web
{
    [TestFixture]
    public class LikesModuleTests
    {
        [TestCase("POST", "/activityFeed/updates/123/likes")]
        [TestCase("DELETE", "/activityFeed/updates/123/likes")]
        public void When_user_is_not_authenticated_Then_routes_return_Unauthorized(string verb, string route)
        {
            var userIdentityProvider = IdentityProviderMock.WithAnonymousUser();
            var browser = new Browser(new ActivityFeedApiHandler(userIdentityProvider,
                new LikesModule(
                    new Mock<IActivityFeedService>().Object,
                    userIdentityProvider,
                    new Mock<IUserProfileProvider>().Object)));

            var response = browser.MakeRequest(verb, route);

            Assert.That(response.StatusCode, Is.EqualTo((int)HttpStatusCode.Unauthorized));
        }

        [Test]
        public void POST_to_likes_for_non_existing_update_reutnrs_NotFound()
        {
            const string updateId = "update/123";

            var activityFeedServiceMock = new Mock<IActivityFeedService>(MockBehavior.Strict);
            activityFeedServiceMock.Setup(service => service.GetUpdate(updateId)).Returns(null as Update);

            var userIdentityProvider = IdentityProviderMock.With("john");
            var browser = new Browser(new ActivityFeedApiHandler(userIdentityProvider,
                new LikesModule(
                    activityFeedServiceMock.Object,
                    userIdentityProvider,
                    new Mock<IUserProfileProvider>().Object)));

            var response = browser.PostJson(String.Format("/activityFeed/updates/{0}/likes", Url.Encode(updateId)), new object());

            Assert.That(response.StatusCode, Is.EqualTo((int)HttpStatusCode.NotFound));
        }

        [Test]
        public void Given_authenticated_user_POST_to_likes_adds_like_by_the_user()
        {
            const string updateId = "update/123";

            var activityFeedServiceMock = new Mock<IActivityFeedService>(MockBehavior.Strict);
            var update = DummyUpdate.From("aguy");
            activityFeedServiceMock.Setup(service => service.GetUpdate(updateId)).Returns(update);

            var userInfoProviderMock = new Mock<IUserProfileProvider>();
            userInfoProviderMock.Setup(provider => provider.GetUserProfile("john")).Returns(new FakeUserInfo
                                                                                             {
                                                                                                 Name = "Stefan"
                                                                                             });

            var userIdentityProvider = IdentityProviderMock.With("john");
            var browser = new Browser(new ActivityFeedApiHandler(userIdentityProvider,
                new LikesModule(
                    activityFeedServiceMock.Object,
                    userIdentityProvider,
                    userInfoProviderMock.Object)));

            var response = browser.PostJson(String.Format("/activityFeed/updates/{0}/likes", Url.Encode(updateId)), new object());

            response.DeserializeBody<LikeEntryDto>();

            Assert.That(update.GetLikes().Count(), Is.EqualTo(1));
            Assert.That(update.GetLikes().Single().UserId, Is.EqualTo("john"));
        }

        // remove like
        [Test]
        public void DELETE_to_likes_for_non_existing_update_returns_NotFound()
        {
            var activityFeedServiceMock = new Mock<IActivityFeedService>(MockBehavior.Strict);
            activityFeedServiceMock.Setup(service => service.GetUpdate("222")).Returns(null as Update);

            var userIdentityProvider = IdentityProviderMock.With("john");
            var browser = new Browser(new ActivityFeedApiHandler(userIdentityProvider,
                new LikesModule(
                    activityFeedServiceMock.Object,
                    userIdentityProvider,
                    new Mock<IUserProfileProvider>().Object)));

            var response = browser.Delete("/activityFeed/updates/222/likes");

            Assert.That(response.StatusCode, Is.EqualTo((int)HttpStatusCode.NotFound));
        }
    }
}